home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / MPExceptionTest ƒ / MPExceptionTest.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-27  |  15.4 KB  |  526 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        "MPExceptionTest.c"
  3.     
  4.     Description:    This is a application to test/demo the MT/MP MPDelayUntil API.
  5.  
  6.     Version:    v0.0
  7.  
  8.     File Ownership:
  9.  
  10.         DRI:                George Warner
  11.  
  12.         Other Contact:        
  13.  
  14.         Technology:            MultiTasking/MultiProcessing
  15.  
  16.     Copyright:     © Copyright 2000 Apple Computer, Inc. All rights reserved.
  17.     
  18.     Disclaimer:    IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
  19.                 ("Apple") in consideration of your agreement to the following terms, and your
  20.                 use, installation, modification or redistribution of this Apple software
  21.                 constitutes acceptance of these terms.  If you do not agree with these terms,
  22.                 please do not use, install, modify or redistribute this Apple software.
  23.  
  24.                 In consideration of your agreement to abide by the following terms, and subject
  25.                 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
  26.                 copyrights in this original Apple software (the "Apple Software"), to use,
  27.                 reproduce, modify and redistribute the Apple Software, with or without
  28.                 modifications, in source and/or binary forms; provided that if you redistribute
  29.                 the Apple Software in its entirety and without modifications, you must retain
  30.                 this notice and the following text and disclaimers in all such redistributions of
  31.                 the Apple Software.  Neither the name, trademarks, service marks or logos of
  32.                 Apple Computer, Inc. may be used to endorse or promote products derived from the
  33.                 Apple Software without specific prior written permission from Apple.  Except as
  34.                 expressly stated in this notice, no other rights or licenses, express or implied,
  35.                 are granted by Apple herein, including but not limited to any patent rights that
  36.                 may be infringed by your derivative works or by other works in which the Apple
  37.                 Software may be incorporated.
  38.  
  39.                 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
  40.                 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  41.                 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42.                 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
  43.                 COMBINATION WITH YOUR PRODUCTS.
  44.  
  45.                 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  46.                 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  47.                 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48.                 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
  49.                 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
  50.                 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
  51.                 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  52.  
  53.     Writers:
  54.  
  55.         gaw    - George Warner
  56.  
  57.     Change History (most recent first):
  58.  
  59.          <1>    02/29/00    gaw     Initial build
  60.  
  61.     Author Initials:
  62.  
  63.     gaw - George Warner
  64.  
  65. */
  66.  
  67. //**************************************************
  68. #pragma mark #Includes
  69. //**************************************************
  70. #include <MacTypes.h>
  71. #include <Fonts.h>
  72. #include <Multiprocessing.h>
  73.  
  74. #include <stdio.h>            // for printf & fflush
  75. #include <SIOUX.h>            // for SIOUXSettings stuff
  76. #include <SIOUXGlobals.h>    // for SIOUXQuitting
  77. //**************************************************
  78. #pragma mark typedefs, structs, enums, defines, etc.
  79. //**************************************************
  80. #define    REGISTER_DEBUGGER    1    // 0 == MPSetExceptionHandler, 0 != MPRegisterDebugger
  81. #define USE_STATE            1    // !0 == set & log task state variable
  82. #define USE_TRAP            1    // 0 == System Call, !0 == trap instruction
  83. //**************************************************
  84. #if USE_STATE
  85. #define SET_STATE(x) { gState = (x);}
  86. #define GET_STATE() (gState)
  87. #define LOG_STATE(s) {printf("%s; GET_STATE() = %8.8lX.\n",(s),GET_STATE());}
  88. #else
  89. #define SET_STATE(x) {}
  90. #define GET_STATE() (-1)
  91. #define LOG_STATE(s) {}
  92. #endif USE_STATE
  93. //**************************************************
  94. #pragma mark static (local) function prototypes
  95. //**************************************************
  96. #if USE_TRAP
  97. static asm UInt32 TRAP(const SInt32 pR3,const SInt32 pR4);
  98.  
  99. static asm UInt32 TRAP_EQ(const SInt32 pR3,const SInt32 pR4);
  100. static asm UInt32 TRAP_NE(const SInt32 pR3,const SInt32 pR4);
  101. static asm UInt32 TRAP_LT(const SInt32 pR3,const SInt32 pR4);
  102. static asm UInt32 TRAP_GT(const SInt32 pR3,const SInt32 pR4);
  103. static asm UInt32 TRAP_LE(const SInt32 pR3,const SInt32 pR4);
  104. static asm UInt32 TRAP_GE(const SInt32 pR3,const SInt32 pR4);
  105.  
  106. static asm UInt32 TRAP_LEQ(const UInt32 pR3,const UInt32 pR4);
  107. static asm UInt32 TRAP_LNE(const UInt32 pR3,const UInt32 pR4);
  108. static asm UInt32 TRAP_LLT(const UInt32 pR3,const UInt32 pR4);
  109. static asm UInt32 TRAP_LGT(const UInt32 pR3,const UInt32 pR4);
  110. static asm UInt32 TRAP_LLE(const UInt32 pR3,const UInt32 pR4);
  111. static asm UInt32 TRAP_LGE(const UInt32 pR3,const UInt32 pR4);
  112. #else
  113. static asm UInt32 System_Call(const UInt32 pR3);
  114. #endif USE_TRAP
  115. static OSStatus MyTask(void *parameter);
  116. static OSStatus Poll_MPTaskQueues(void);
  117. //**************************************************
  118. #pragma mark typedefs, structs, enums, defines, etc.
  119. //**************************************************
  120. static MPTaskID            gMPTaskID        = kInvalidID;
  121. static MPSemaphoreID    gMPSemaphoreID    = kInvalidID;
  122. static MPQueueID        gMPQueueID        = kInvalidID;
  123. static OSStatus            gOSStatus        = noErr;
  124. #if USE_STATE
  125. static UInt32            gState            = -1;
  126. #endif USE_STATE
  127. static UInt32            gPass = 5;
  128. //**************************************************
  129. #pragma mark exported functions
  130. //**************************************************
  131. void main(void)
  132. {
  133.     OSStatus                    anErr;
  134.     volatile Boolean            done = false;
  135.  
  136.     // Set the SIOUX window defaults
  137.     SIOUXSettings.autocloseonquit    = false;
  138.     SIOUXSettings.asktosaveonclose    = false;
  139.     SIOUXSettings.showstatusline    = false;
  140.     SIOUXSettings.columns            = 132;
  141.     SIOUXSettings.rows                = 24;
  142.     SIOUXSettings.fontsize            = 10;
  143.     GetFNum("\pMonaco",&SIOUXSettings.fontid);
  144.     SIOUXSettings.standalone        = true;
  145.  
  146.     printf("MPExceptionTest starting!\n");
  147.  
  148.     // Make sure that the MP library is loaded
  149.     if    (!MPLibraryIsLoaded())
  150.     {
  151.         printf("The MP library did not load.\n");
  152.         return;
  153.     }
  154.  
  155.     {    // for giggles we'll dump out the MP Library version info
  156.         Ptr tVersionCStringPtr;
  157.         UInt32 major,minor,release,revision;
  158.  
  159.         _MPLibraryVersion(&tVersionCStringPtr,&major,&minor,&release,&revision);
  160.  
  161.         printf("\n Version: \"%s\", major: %ld, minor: %ld, release: %ld, revision: %ld.\n",tVersionCStringPtr,major,minor,release,revision);
  162.     }
  163.  
  164.     // create our trigger semaphore
  165.     anErr = MPCreateSemaphore(1,0,&gMPSemaphoreID);
  166.     if (noErr != anErr)
  167.         printf("MPCreateSemaphore error: %ld.\n", anErr);
  168.     else
  169.         printf("Trigger semaphore created...\n");
  170.  
  171.     SET_STATE(0);
  172.     LOG_STATE("Initializing state");
  173.  
  174.     // create our task
  175.     anErr = MPCreateTask(MyTask, (void *) &gMPSemaphoreID,0,kInvalidID,nil,nil,kNilOptions,&gMPTaskID);
  176.     if (noErr != anErr)
  177.         printf("MPCreateTask error: %ld.\n", anErr);
  178.     else
  179.         printf("Task created...\n");
  180.  
  181.     LOG_STATE("After MPCreateTask");
  182.  
  183.     // create the exception queue
  184.     anErr = MPCreateQueue(&gMPQueueID);
  185.     if (noErr != anErr)
  186.         printf("MPCreateQueue error: %ld.\n", anErr);
  187.     else
  188.         printf("exception Queue created...\n");
  189.  
  190. #if REGISTER_DEBUGGER
  191.     anErr = MPRegisterDebugger(gMPQueueID,100);
  192.     if (noErr != anErr)
  193.         printf("MPRegisterDebugger error: %ld.\n", anErr);
  194.     else
  195.         printf("Debugger registered...\n");
  196. #else
  197.     // set the exception queue for our task
  198.     anErr = MPSetExceptionHandler(gMPTaskID,gMPQueueID);
  199.     if (noErr != anErr)
  200.         printf("MPSetExceptionHandler error: %ld.\n", anErr);
  201.     else
  202.         printf("ExceptionHandler set...\n");
  203. #endif REGISTER_DEBUGGER
  204.  
  205.     LOG_STATE("Before MPSignalSemaphore");
  206.  
  207.     // trigger the task to throw an exception
  208.     anErr = MPSignalSemaphore(gMPSemaphoreID);
  209.     if (noErr != anErr)
  210.         printf("MPSignalSemaphore error: %ld.\n", anErr);
  211.     else
  212.         printf("Semaphore signaled...\n");
  213.  
  214.     LOG_STATE("After MPSignalSemaphore");
  215.  
  216.     // it's importaint that our WaitNextEvent loop not be CPU bound
  217.     // so we use a sleep time of one with WNE.
  218.     while (!done && (noErr == anErr) && !SIOUXQuitting)
  219.     {
  220.         EventRecord theEvent;
  221.  
  222.         WaitNextEvent(everyEvent,&theEvent,1,nil);
  223.         SIOUXHandleOneEvent(&theEvent);    // tell SIOUX to handle the event
  224.  
  225.         anErr = Poll_MPTaskQueues();
  226.     }
  227.  
  228. #if REGISTER_DEBUGGER
  229.     if (noErr == anErr)
  230.         anErr = MPUnregisterDebugger(gMPQueueID);
  231.     else
  232.         (void) MPUnregisterDebugger(gMPQueueID);
  233. #endif REGISTER_DEBUGGER
  234.  
  235.     // Now cleanup (delete) our trigger semaphore, task & exception queue.
  236.     if (kInvalidID != gMPSemaphoreID)
  237.         MPDeleteSemaphore(gMPSemaphoreID);
  238.  
  239.     if (kInvalidID != gMPTaskID)
  240.         MPTerminateTask(gMPTaskID,-1);
  241.  
  242.     if (kInvalidID != gMPQueueID)
  243.         MPDeleteQueue(gMPQueueID);
  244.  
  245.     // if we had an error then report it
  246.     if (noErr != anErr)
  247.         printf("Error: %ld.",anErr);
  248.  
  249.     if (noErr == anErr)
  250.         printf("Done!\n");
  251.  
  252. //    printf("Press command-Q to quit.");
  253. }
  254. //**************************************************
  255. #pragma mark static (local) functions
  256. //**************************************************
  257. #if USE_TRAP
  258. static asm UInt32 TRAP(/* const SInt32 pR3,const SInt32 pR4 */)
  259. {
  260.     tw    0x1F,r3,r4    // LT | GT | EQ | LO | HI    (trap r3,r4)
  261.     blr
  262. }
  263.  
  264. static asm UInt32 TRAP_EQ(/* const SInt32 pR3,const SInt32 pR4 */)
  265. {
  266.     tweq     r3,r4
  267.     blr
  268. }
  269. static asm UInt32 TRAP_NE(/* const SInt32 pR3,const SInt32 pR4 */)
  270. {
  271.     twne     r3,r4
  272.     blr
  273. }
  274. static asm UInt32 TRAP_LT(/* const SInt32 pR3,const SInt32 pR4 */)
  275. {
  276.     twlt    r3,r4    // LT
  277.     blr
  278. }
  279. static asm UInt32 TRAP_GT(/* const SInt32 pR3,const SInt32 pR4 */)
  280. {
  281.     twgt    r3,r4    // GT
  282.     blr
  283. }
  284. static asm UInt32 TRAP_LE(/* const SInt32 pR3,const SInt32 pR4 */)
  285. {
  286.     twle    r3,r4    // LT | EQ
  287.     blr
  288. }
  289. static asm UInt32 TRAP_GE(/* const SInt32 pR3,const SInt32 pR4 */)
  290. {
  291.     twge    r3,r4    // GT | EQ
  292.     blr
  293. }
  294.  
  295. static asm UInt32 TRAP_LEQ(/* const UInt32 pR3,const UInt32 pR4 */)
  296. {
  297.     tweq     r3,r4
  298.     blr
  299. }
  300. static asm UInt32 TRAP_LNE(/* const UInt32 pR3,const UInt32 pR4 */)
  301. {
  302.     twne     r3,r4
  303.     blr
  304. }
  305. static asm UInt32 TRAP_LLT(/* const UInt32 pR3,const UInt32 pR4 */)
  306. {
  307.     twllt    r3,r4    // LT
  308.     blr
  309. }
  310. static asm UInt32 TRAP_LGT(/* const UInt32 pR3,const UInt32 pR4 */)
  311. {
  312.     twlgt    r3,r4    // GT
  313.     blr
  314. }
  315. static asm UInt32 TRAP_LLE(/* const UInt32 pR3,const UInt32 pR4 */)
  316. {
  317.     twlle    r3,r4    // LT | EQ
  318.     blr
  319. }
  320. static asm UInt32 TRAP_LGE(/* const UInt32 pR3,const UInt32 pR4 */)
  321. {
  322.     twlge    r3,r4    // GT | EQ
  323.     blr
  324. }
  325. #else
  326. // This is used to throw a system call exception
  327. static asm UInt32 System_Call(/* const UInt32 pR3 */)
  328. {
  329.     sc
  330.     blr
  331. }
  332. #endif
  333.  
  334. // This is our MP task
  335. static OSStatus MyTask(void *parameter)
  336. {
  337.     OSErr anErr = noErr;
  338.     SInt32 count = 0;
  339.  
  340.  
  341.     if (noErr == anErr)
  342.     {
  343.         while (noErr == anErr)
  344.         {
  345.             SET_STATE(1);
  346.             anErr = MPWaitOnSemaphore(*(MPSemaphoreID*) parameter,kDurationForever);
  347.  
  348.             SET_STATE(2);
  349.  
  350.             if (noErr == anErr)
  351. #if USE_TRAP
  352.                 anErr = TRAP(count++,0);
  353. #else
  354.                 anErr = System_Call(count++);
  355. #endif USE_TRAP
  356.             SET_STATE(3);
  357.         }
  358.         SET_STATE(4);
  359.     }
  360.  
  361.     // and return our status.
  362.     return anErr;
  363. }
  364.  
  365. static OSStatus Poll_MPTaskQueues(void)
  366. {
  367.     SInt32 expMPTaskID,expType,p3;
  368.     OSStatus anErr = noErr;
  369.  
  370.     // see if our exception queue has anything for us
  371.     anErr = MPWaitOnQueue(gMPQueueID,(void*) &expMPTaskID,(void*) &expType,(void*) &p3,kDurationImmediate);
  372.     if (kMPTimeoutErr == anErr)    // if queue not ready yet...
  373.         anErr = noErr;            // ... ignore the error
  374.     else if (noErr == anErr)    // otherwise...
  375.     {
  376.         MachineInformationPowerPC    tMachineInfo;
  377.         RegisterInformationPowerPC    tRegisterInfo;
  378.         UInt32 *tUInt32Ptr,tUInt32;
  379.  
  380.         // ... let us know!
  381.         printf("•exception queue notified of task #%8.8lX - ",expMPTaskID,expType,gPass);
  382.  
  383.         switch (expType)
  384.         {
  385.         case    kUnknownException:
  386.             printf("Unknown exception.\n");
  387.             break;
  388.         case    kIllegalInstructionException:
  389.             printf("Illegal Instruction exception.\n");
  390.             break;
  391.         case    kTrapException:
  392.             printf("Trap exception.\n");
  393.             break;
  394.         case    kAccessException:
  395.             printf("Access exception.\n");
  396.             break;
  397.         case    kUnmappedMemoryException:
  398.             printf("Unmapped memory exception.\n");
  399.             break;
  400.         case    kExcludedMemoryException:
  401.             printf("Excluded memory exception.\n");
  402.             break;
  403.         case    kReadOnlyMemoryException:
  404.             printf("Read-only memory exception.\n");
  405.             break;
  406.         case    kUnresolvablePageFaultException:
  407.             printf("Unresolvable page fault exception.\n");
  408.             break;
  409.         case    kPrivilegeViolationException:
  410.             printf("Privilege violation exception.\n");
  411.             break;
  412.         case    kTraceException:
  413.             printf("Trace exception.\n");
  414.             break;
  415.         case    kInstructionBreakpointException:
  416.             printf("Instruction breakpoint exception.\n");
  417.             break;
  418.         case    kDataBreakpointException:
  419.             printf("Data breakpoint exception.\n");
  420.             break;
  421.         case    kIntegerException:
  422.             printf("Integer exception.\n");
  423.             break;
  424.         case    kFloatingPointException:
  425.             printf("Floating point exception.\n");
  426.             break;
  427.         case    kStackOverflowException:
  428.             printf("Stack overflow exception.\n");
  429.             break;
  430.         case    kTaskTerminationException:
  431.             printf("Task termination exception.\n");
  432.             break;
  433.         case    kTaskCreationException:
  434.             printf("Task creation exception.\n");
  435.             break;
  436.         default:
  437.             printf("Undefined exception type: %8.8lX.\n",expType);
  438.             break;
  439.         }
  440.  
  441.         LOG_STATE("    After exception");
  442.  
  443.         anErr = MPExtractTaskState(gMPTaskID,kMPTaskStateMachine,&tMachineInfo);
  444.         if (noErr != anErr)
  445.             printf("    MPExtractTaskState(%8.8lX,kMPTaskStateMachine) error: %ld.\n",
  446.                 gMPTaskID, anErr);
  447.         else
  448.         {
  449.             printf("    Task machine state extracted. ");
  450.  
  451.             tUInt32Ptr = (UInt32*) tMachineInfo.PC.lo;
  452.             tUInt32 = *tUInt32Ptr;
  453. #if USE_TRAP
  454.             if (0x7FE32008 != tUInt32)    // if this wasn't a trap instruction...
  455. #else
  456.             if (0x44000002 != tUInt32)    // if this wasn't a system call instruction...
  457. #endif USE_TRAP
  458.                 printf("(PC: %8.8lX, instruction @ PC: %8.8lX)\n",tUInt32Ptr,tUInt32);
  459.             else
  460.             {
  461. #if USE_TRAP
  462.                 printf("(PC: %8.8lX, instruction @ PC: %8.8lX (trap))\n",tUInt32Ptr,tUInt32);
  463. #else
  464.                 printf("(PC: %8.8lX, instruction @ PC: %8.8lX (System call))\n",tUInt32Ptr,tUInt32);
  465. #endif USE_TRAP
  466.  
  467.                 tMachineInfo.PC.lo += 4;        // ...skip past the instruction.
  468.  
  469.                 anErr = MPSetTaskState(gMPTaskID,kMPTaskStateMachine,&tMachineInfo);
  470.                 if (noErr != anErr)
  471.                     printf("    MPSetTaskState(%8.8lX,kMPTaskStateMachine) error: %ld.\n",gMPTaskID, anErr);
  472.                 else
  473.                     printf("    Task machine state set (PC += 4).\n");
  474.  
  475.                 anErr = MPExtractTaskState(gMPTaskID,kMPTaskStateRegisters,&tRegisterInfo);
  476.                 if (noErr != anErr)
  477.                     printf("    MPExtractTaskState(%8.8lX,kMPTaskStateRegisters) error: %ld.\n",
  478.                         gMPTaskID, anErr);
  479.                 else
  480.                 {
  481.                     printf("    Task register state extracted (R3: %8.8lX).\n",tRegisterInfo.R3.lo);
  482.  
  483.                     if (0 == gPass)                    // if this is the last time...
  484.                         tRegisterInfo.R3.lo = -1;    // ... then this will return an error!
  485.                     else                            // ... otherwise ...
  486.                         tRegisterInfo.R3.lo = 0;        // ... it won't!
  487.  
  488.                     anErr = MPSetTaskState(gMPTaskID,kMPTaskStateRegisters,&tRegisterInfo);
  489.                     if (noErr != anErr)
  490.                         printf("    MPSetTaskState(%8.8lX,kMPTaskStateRegisters) error: %ld.\n",gMPTaskID, anErr);
  491.                     else
  492.                         printf("    Task register state set (R3: %8.8lX).\n",tRegisterInfo.R3.lo);
  493.                 }
  494.             }
  495.         }
  496.  
  497.         // now dispose of the exception and resume the task.
  498.         anErr = MPDisposeTaskException(gMPTaskID,kMPTaskResumeMask);
  499.         if (noErr != anErr)
  500.             printf("    MPDisposeTaskException error: %ld.\n", anErr);
  501.         else
  502.             printf("    Exception Disposed...\n");
  503.  
  504.         LOG_STATE("    After MPDisposeTaskException");
  505.  
  506.         if (0 < gPass)
  507.         {
  508.             gPass--;
  509.  
  510.             // trigger the task to throw an exception
  511.             anErr = MPSignalSemaphore(gMPSemaphoreID);
  512.             if (noErr != anErr)
  513.                 printf("    MPSignalSemaphore error: %ld.\n", anErr);
  514.             else
  515.                 printf("    Semaphore signaled...\n");
  516.         }
  517.     }
  518.  
  519.     if (noErr != gOSStatus)
  520.     {
  521.         printf("•Task Error: %ld.\n",gOSStatus);
  522.         gOSStatus = noErr;
  523.     }
  524.     return anErr;
  525. }
  526.